package testdatagenerator;

import Storage.DBConnect;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Vector;

public class packet {

    private static Vector<Double> delays = new Vector<Double>();
    private static int plogid = 0;
    private String timeSo;
    private Calendar time, vtime, timeSoo;
    private boolean failure;
    private char msgType;
    private int timeToLive, dest, origin, msgNum, seqNum, hopCount;
    private int length, msglength, watcher;
    private String message;
    private static DBConnect dbConnection;

    public static double getStdDev() {
        double sum = 0;
        for (int i = 0; i < delays.size(); i++) {
            sum += delays.get(i);
            System.out.println(delays.get(i));
        }
        double mean = sum / delays.size(), stdDev = 0;
        System.out.println(mean);
        for (int i = 0; i < delays.size(); i++) {
            stdDev += (delays.get(i) - mean) * (delays.get(i) - mean);
        }
        return Math.sqrt(stdDev / delays.size());
    }

    //tell this packet at what node it started at
    public void setOrigin(int start) {
        origin = start;
    }

    //set the time at which the data becomes invalid
    public void setVtime(Calendar a) {
        vtime = a;
    }

    //get the time at which the data becomes invalid
    public Calendar getVtime() {
        return vtime;
    }

    public char getMsgType() {
        return msgType;
    }

    public void setMsgType(char c) {
        msgType = c;
    }

    public void setWatcher(int Watcher) {
        watcher = Watcher;
    }

    public int getWatcher() {
        return watcher;
    }

    public packet(int dest, int timeToLive, double Vtime) {
        if (dbConnection == null) {
            dbConnection = new DBConnect();
            dbConnection.connectToDatabase();
            System.out.println(dbConnection.getErrorMessage());
        }
        init(dest, timeToLive, Calendar.getInstance(), Vtime);
    }

    public packet(int dest, int timeToLive, Calendar time, double Vtime) {
        if (dbConnection == null) {
            dbConnection = new DBConnect();
            dbConnection.connectToDatabase();
            System.out.println(dbConnection.getErrorMessage());
        }
        init(dest, timeToLive, time, Vtime);
    }

    public void init(int dest, int timeToLive, Calendar time, double Vtime) {
        length = 100;
        msglength = 80;
        vtime = Calendar.getInstance();
        vtime.setTime(time.getTime());
        vtime.add(Calendar.MILLISECOND, (int) (Vtime * 1000));
        watcher = 0;
        msgNum = 1;
        seqNum = 1;
        hopCount = 0;
        msgType = 'd';
        message = "";
        this.dest = dest;
        this.time = time;
        this.timeSo = "";
        this.timeToLive = timeToLive;
    }

    public void setMessage(String s) {
        message = s;
    }

    public String getMessage() {
        return message;
    }

    public int getMsgNum() {
        return msgNum;
    }

    public int getSeqNum() {
        return seqNum;
    }

    public int getOrigin() {
        return origin;
    }

    public int getDest() {
        return dest;
    }

    public Calendar getTime() {
        return time;
    }

    public void setMsgSeqNum(int num) {
        msgNum = num;
    }

    public void setPackSeqNum(int num) {
        seqNum = num;
    }

    //Tell this packet that it has been sent from one node to another
    public void updatePacket(double delay, Node prev, Node sender, Node receiver, char opmode) {
        plogid++;
        if (opmode == 's') {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            timeSo = format.format(time.getTime());
        }
        //log these changes to the file
        GiantString s = GiantString.getGiantString();
        s.add(plogid);
        s.add(sender.getId());
        s.add(sender.getIp());
        s.add(opmode);
        s.add(msgType);
        s.add(length);
        s.add(seqNum);
        s.add(msglength);
        s.add(msgNum);
        s.add(timeSo);
        //s.add(timeSoo);
        //in the case of creating the packet delay is always zero
        if (opmode != 's') {
            delays.add(delay);
        }
        time.add(Calendar.MILLISECOND, (int) (delay * 1000));
        s.add(time);
        s.add((vtime.getTimeInMillis() - time.getTimeInMillis()) / 1000);
        s.add(Node.getIpById(origin));
        s.add(Node.getIpById(dest));
        if (receiver != null) {
            s.add(receiver.getId());
            s.add(receiver.getIp());
        } else {
            s.add(0);
            s.add(0);
        }
        if (prev != null) {
            s.add(prev.getId());
            s.add(prev.getIp());
        } else {
            s.add(0);
            s.add(0);
        }
        s.add(timeToLive);
        s.add(hopCount);
        s.add(sender.getNumNeigh());
        s.add(watcher);
        dbConnection.executeQuery("INSERT INTO LOG VALUES(" + s.toString()+ ")", false);
        s.Done();
        //end of logging these changes to a file
        timeToLive--;
        hopCount++;
    }

    //Get how many hopes are left before this packet gives up on reaching its destination
    public int getTimeToLive() {
        return timeToLive;
    }

    //Events to be performed if the packet could not make it to its destination
    public void logFailure() {
        failure = true;
    }

    //Events to be performed if the packet arrived at its destination
    public void logSuccess() {
        failure = false;
    }

    //return whether or not this packet made it to its destination successfully or not
    public boolean success() {
        return !failure;
    }
}
